<?php


namespace app\api\controller\v1;


use addons\epay\library\Service;
use app\common\controller\Api;
use app\common\library\Email;
use app\extra\wx\WxSdk;
use fast\Random;
use think\Db;
use think\Log;
use think\Request;

/**
 * 订单接口
 */
class Order extends Api
{
    protected $noNeedLogin = ['notify_pay', 'notify_refund', 'test'];
    protected $noNeedRight = '*';
    protected static $status = [
        -1 => '已超时',
        0  => '待付款',
        1  => '已付款',
        2  => '已使用',
        3  => '已到期',
        4  => '已退款'
    ];

    // 会员卡类型
    protected static $type = [
        1 => '次卡',
        2 => '私教卡',
        3 => '周卡',
        4 => '月卡',
        5 => '学生卡'
    ];

    // 订单有效期
    protected static $expires = [
        // 【次卡】每次7天有效期；可使用一次
        1 => 60 * 60 * 24 * 7,
        // 【私教卡】每次7天有效期；可使用一次
        2 => 60 * 60 * 24 * 7,
        // 【周卡】21天有效期；可使用一周
        3 => 60 * 60 * 24 * 7 * 3,
        // 【月卡】90天有效期；可使用一个月
        4 => 60 * 60 * 24 * 30 * 3,
        // 【学生卡】90天有效期；可使用一个月
        5 => 60 * 60 * 24 * 30 * 3,
    ];

    // 订单超时时间
    protected static $out_time = 60 * 10;

    // 订单有效期截止，通知时间
    protected static $validity_time = 60 * 60 * 72;

    protected function _initialize()
    {
        parent::_initialize(); // TODO: Change the autogenerated stub
    }

    /**
     * 订单列表、详情：传入订单主键返回详情，只传入订单状态返回列表 ALL=全部
     * @ApiMethod (GET)
     * @param int $id 订单主键：id
     * @param int $status 订单状态：status
     */
    public function index()
    {
        if ($this->request->isGet()) {

            $id     = input('id');
            $status = input('status');

            if (!$id && $status == '') {
                $this->error('必传一个参数');
            }
            if ($status == "ALL") {
                $status = ['<>', -2];
            }

            if ($id) {
                $result = Db::name('order')
                    ->where(['id' => $id])
                    ->field('user_id,good_name,thumb_image,content,numbers,total_price,status,pay_time,refund_time,createtime,validity_time')
                    ->find();
                if ($result) {
                    $result['user_id'] != $this->auth->id && $this->error('获取失败,此订单不属于该用户');
                    unset($result['user_id']);
                    $result['status_text'] = self::$status[$result['status']];
                    $result['thumb_image'] = self::patch_cdn($result['thumb_image']);
                    $result['pay_time'] && $result['pay_time'] = date("Y-m-d H:i:s", $result['pay_time']);
                    $result['refund_time'] && $result['refund_time'] = date("Y-m-d H:i:s", $result['refund_time']);
                    $result['createtime']    = date("Y-m-d H:i:s", $result['createtime']);
                    $result['validity_time'] = date("Y-m-d H:i:s", $result['validity_time']);

                    $this->success('获取成功', $result);
                } else {
                    $this->error('获取失败,订单信息不存在');
                }
            } else {
                $result = Db::name('order')
                    ->where(['status' => $status, 'user_id' => $this->auth->id])
                    ->field('id,good_name,thumb_image,numbers,total_price,status,pay_time,refund_time,createtime')
                    ->order('createtime', 'desc')
                    ->paginate(null, false, $this->paginate)
                    ->each(function ($item) {
                        $item['thumb_image'] = self::patch_cdn($item['thumb_image']);
                        $item['status_text'] = self::$status[$item['status']];
                        $item['pay_time'] && $item['pay_time'] = date("Y-m-d H:i:s", $item['pay_time']);
                        $item['refund_time'] && $item['refund_time'] = date("Y-m-d H:i:s", $item['refund_time']);
                        $item['createtime'] = date("Y-m-d H:i:s", $item['createtime']);
                        return $item;
                    });
            }

            $this->success('获取成功', $result);
        } else {
            $this->error(ErrorCode::$ERROR['ERROR_METHOD']);
        }
    }

    /**
     * 下单，返回预支付信息；校验场馆、教练、会员卡
     * @ApiMethod (POST)
     * @param int $good_id 会员卡主键：good_id
     */
    public function create()
    {
        if ($this->request->isPost()) {
            $good_id = input('good_id');
            !$good_id && $this->error('请传入会员卡主键');
            $time = time();

            $good = Db::name('good')->where(['id' => $good_id])->field('is_discount,stock,name,gymnasium_id,coach_id,end_number,type,thumb_image,content_,full_image,price,status')->find();
            // 验证会员卡
            if ($good) {
                $good['status'] !== 1 && $this->error('该会员卡已下架');
                // 会员卡是优惠卡的情况
                if ($good['is_discount'] == 1) {
                    // 判断库存
                    $good['stock'] < 1 && $this->error('该活动卡已售罄');
                    // 查询优惠券
                    $find_extension_type = $good['type'] == 3 ? 1 : 2;
                    $find_extension      = Db::name('extension_001')->where(['user_id' => $this->auth->id, 'type' => $find_extension_type])->field('id,type,status,end_time')->find();
                    if ($find_extension) {
                        if ($find_extension['status'] != 0) {
                            $this->error('优惠券已到期，或已使用');
                        }
                        if ($find_extension['end_time'] < $time) {
                            Db::name('extension_001')->where(['id' => $find_extension['id']])->update(['status' => 2]);
                            $this->error('优惠券已过期');
                        }
                    } else {
                        $this->error('您暂时没有优惠券，无法购买活动卡');
                    }
                }

                // 验证场馆
                $gymnasium = Db::name('gymnasium')->where(['id' => $good['gymnasium_id']])->field('status')->find();
                if ($gymnasium) {
                    $good['status'] !== 1 && $this->error('该会员卡行方，已被禁用');

                    // 教练卡验证教练
                    if ($good['type'] == 2) {
                        $coach = Db::name('coach')->where(['id' => $good['coach_id']])->field('status')->find();
                        if ($coach) {
                            $coach['status'] !== 1 && $this->error('该会员卡的教练，已被禁用');
                        } else {
                            $this->error('找不到该会员卡的教练');
                        }
                    }
                } else {
                    $this->error('找不到该会员卡的发行方');
                }
            } else {
                $this->error('无效的会员卡信息');
            }

            Db::startTrans();
            try {
                $numbers        = $time . Random::numeric(10);
                $price          = $good['price'];
                $discount_price = 0;
                if ($good['is_discount'] == 1 && $good['type'] == 3) {
                    $price          = $good['price'] - 99;
                    $discount_price = 99;
                }
                if ($good['is_discount'] == 1 && $good['type'] == 4) {
                    $price          = $good['price'] - 300;
                    $discount_price = 300;
                }
                $params = [
                    'amount'    => $price,
                    'orderid'   => $numbers,
                    'type'      => 'wechat',
                    'title'     => mb_substr($good['name'], 0, 15),
                    'notifyurl' => Request::instance()->root(true) . '/api/v1/order/notify_pay/numbers/' . $numbers,
                    'method'    => "mp",
                    'openid'    => $this->auth->open_id
                ];
                $result = Service::submitOrder($params);

                // 订单表
                Db::name('order')->insert([
                    'user_id'        => $this->auth->id,
                    'gymnasium_id'   => $good['gymnasium_id'],
                    'coach_id'       => $good['coach_id'],
                    'end_number'     => $good['end_number'],
                    'good_id'        => $good_id,
                    'numbers'        => $numbers,
                    'good_name'      => $good['name'],
                    'thumb_image'    => $good['thumb_image'],
                    'full_image'     => $good['full_image'],
                    'good_type'      => $good['type'],
                    'content'        => $good['content_'],
                    'total_price'    => $price,
                    'discount_price' => $discount_price,
                    'is_discount'    => $good['is_discount'],
                    'createtime'     => $time,
                    'updatetime'     => $time,
                ]);

                // 两小时超时，订阅过期通知，将订单转换为超时取消状态
                $redis = new \Redis();
                $redis->pconnect(config('redis.host'), config('redis.port'), config('redis.timeout'));
                $redis->select(1);
                $redis->setex($numbers, self::$out_time, '');

                Db::commit();
            } catch (\Exception $e) {
                Db::rollback();
                $this->error($e->getMessage());
            }
            $add['create_time'] = date('Y-m-d H:i:s');
            $add['order_id']    = $numbers;
            $add['price']       = $price;
            $this->success('下单成功', ['pay' => json_decode($result, true), 'add' => $add]);
        } else {
            $this->error(ErrorCode::$ERROR['ERROR_METHOD']);
        }
    }

    /**
     * 二次支付，返回预支付信息；校验订单、场馆、教练、会员卡
     * @ApiMethod (POST)
     * @param int $id 订单主键：id
     */
    public function payAgain()
    {
        if ($this->request->isPost()) {
            $id = input('id');
            !$id && $this->error('请传入订单主键');

            $order = Db::name('order')->field('is_discount,total_price,coach_id,end_number,numbers,good_id,good_type,gymnasium_id,status,createtime,user_id')->find($id);
            // 验证订单
            if ($order) {
                $order['status'] == -1 && $this->error('订单已取消');
                $order['status'] == 1 && $this->error('订单已支付');
                $order['status'] == 4 && $this->error('订单已退款');
                $order['user_id'] != $this->auth->id && $this->error('此订单不属于该用户');
                if ($order['createtime'] + self::$out_time < time()) {
                    Db::name('order')->where(['id' => $id])->update(['status' => -1, 'updatetime' => time()]);
                    $this->error('订单已超时，自动取消');
                }

                // 验证场馆
                $gymnasium = Db::name('gymnasium')->where(['id' => $order['gymnasium_id']])->field('status')->find();
                if ($gymnasium) {
                    $gymnasium['status'] !== 1 && $this->error('该订单包含会员卡的行方，已被禁用');

                    // 教练卡验证教练
                    if ($order['good_type'] == 2) {
                        $coach = Db::name('coach')->where(['id' => $order['coach_id']])->field('status')->find();
                        if ($coach) {
                            $coach['status'] !== 1 && $this->error('该订单包含会员卡的教练，已被禁用');
                        } else {
                            $this->error('找不到该订单包含会员卡的教练');
                        }
                    }
                } else {
                    $this->error('找不到该订单包含会员卡的发行方');
                }

                // 验证优惠券是否已经使用
                if ($order['is_discount'] == 1) {
                    $good                = Db::name('good')->where(['id' => $order['good_id']])->field('type')->find();
                    $find_extension_type = $good['type'] == 3 ? 1 : 2;
                    $find_extension      = Db::name('extension_001')->where(['user_id' => $order['user_id'], 'type' => $find_extension_type])->find();
                    if ($find_extension) {
                        if ($find_extension['end_time'] < time()) {
                            Db::name('order')->where(['id' => $id])->update(['status' => -1, 'updatetime' => time()]);
                            $this->error('订单包含优惠券已过期，订单自动取消');
                        }
                        if ($find_extension['status'] != 0) {
                            Db::name('order')->where(['id' => $id])->update(['status' => -1, 'updatetime' => time()]);
                            $this->error('订单包含优惠券已使用，订单自动取消');
                        }
                    }
                }

                // 验证会员卡
                $good = Db::name('good')->where(['id' => $order['good_id']])->field('is_discount,stock,price,end_number,name,type,thumb_image,content_,full_image,price,status')->find();
                if ($good) {
                    if ($good['status'] !== 1) {
                        Db::name('order')->where(['id' => $id])->update(['status' => -1, 'updatetime' => time()]);
                        $this->error('该订单包含的会员卡已下架，订单自动取消');
                    }
                    if ($good['type'] !== $order['good_type']) {
                        Db::name('order')->where(['id' => $id])->update(['status' => -1, 'updatetime' => time()]);
                        $this->error('该订单包含的会员卡【类型】发生变化，订单自动取消');
                    }
                    if ($good['end_number'] !== $order['end_number']) {
                        Db::name('order')->where(['id' => $id])->update(['status' => -1, 'updatetime' => time()]);
                        $this->error('该订单包含的会员卡【有效次数】发生变化，订单自动取消');
                    }
                    if ($good['price'] !== $order['total_price'] && $good['is_discount'] != 1) {
                        Db::name('order')->where(['id' => $id])->update(['status' => -1, 'updatetime' => time()]);
                        $this->error('该订单包含的会员卡【价格】发生变化，订单自动取消');
                    }
                } else {
                    $this->error('无效的会员卡信息');
                }
            } else {
                $this->error('订单信息未找到');
            }


            Db::startTrans();
            try {
                $numbers = time() . Random::numeric(10);

                $params = [
                    'amount'    => $order['total_price'],
                    'orderid'   => $numbers,
                    'type'      => 'wechat',
                    'title'     => mb_substr($good['name'], 0, 15),
                    'notifyurl' => Request::instance()->root(true) . '/api/v1/order/notify_pay/numbers/' . $numbers,
                    'method'    => "mp",
                    'openid'    => $this->auth->open_id
                ];

                // 更新订单
                Db::name('order')->where(['id' => $id])->update([
                    'numbers'     => $numbers,
                    'good_name'   => $good['name'],
                    'thumb_image' => $good['thumb_image'],
                    'full_image'  => $good['full_image'],
                    'content'     => $good['content_'],
                    'updatetime'  => time(),
                ]);
                $result = Service::submitOrder($params);

                // 更新缓存 删除之前生成的订单号
                $redis = new \Redis();
                $redis->pconnect(config('redis.host'), config('redis.port'), config('redis.timeout'));
                $redis->select(1);
                $redis->del($order['numbers']);
                $redis->setex($numbers, self::$out_time, '');

                Db::commit();
            } catch (\Exception $e) {
                Db::rollback();
                $this->error($e->getMessage());
            }

            $this->success('获取成功', json_decode($result, true));
        } else {
            $this->error(ErrorCode::$ERROR['ERROR_METHOD']);
        }
    }

    /**
     * 支付回调通知,成功更新缓存、订单有效时间；失败发送邮件警报,更新优惠卡库存
     */
    public function notify_pay()
    {
        $numbers = (string)$this->request->param('numbers');
        $pay     = Service::checkNotify('wechat');
        if (!$pay) {
            echo '签名错误';
            return;
        }
        $data = $pay->verify();
        Db::startTrans();
        try {
            $order = Db::name('order')->where(['numbers' => $numbers])->find();

            // 【有效时间】
            if ($order['good_type'] == 1 || $order['good_type'] == 2) {
                $validity_time = time() + $order['end_number'] * self::$expires[$order['good_type']];
            } else {
                $validity_time = time() + self::$expires[$order['good_type']];
            }

            // 更新订单
            Db::name('order')->where(['numbers' => $numbers])->update([
                'transaction'   => $data['transaction_id'],
                'status'        => 1,
                'pay_time'      => time(),
                'updatetime'    => time(),
                'validity_time' => $validity_time,
            ]);

            // 更新用户优惠券，场馆减库存
            if ($order['is_discount'] == 1) {
                Db::name('good')->where(['id' => $order['good_id']])->setDec('stock');
                $good                = Db::name('good')->where(['id' => $order['good_id']])->field('type')->find();
                $find_extension_type = $good['type'] == 3 ? 1 : 2;
                Db::name('extension_001')->where(['user_id' => $order['user_id'], 'type' => $find_extension_type])->update([
                    'status'     => 1,
                    'use_time'   => time(),
                    'updatetime' => time(),
                ]);
            }

            // 删除db1
            $redis = new \Redis();
            $redis->pconnect(config('redis.host'), config('redis.port'), config('redis.timeout'));
            $redis->select(1);
            $redis->del($numbers);

            // 如果会员卡没有使用，【有效时间】到期前72小时下发过期通知
            $redis->select(2);
            $redis->setex($numbers, $validity_time - self::$validity_time - time(), '');

            // 如果会员卡没有使用，也不退款。需要自动分润
            $redis->select(3);
            $redis->setex($numbers, $validity_time - time(), '');

            Log::info('订单支付成功' . $numbers);
            Log::info($data);

            Db::commit();

            $pay->success();
        } catch (\Exception $e) {
            Db::rollback();

            // 发送邮件警报
            (new Email)->to(config('alarm.email'))
                ->subject('订单支付成功,回调失败')
                ->message('<h1>错误信息：</h1>' . $e->getMessage() . '<h1>错误行号：</h1>' . $e->getLine() . '<h1>回调数据</h1><pre>' . json_encode($data, JSON_UNESCAPED_UNICODE) . '</pre>')
                ->send();

            // 记录错误日志
            Log::error('订单支付成功,回调失败');
            Log::error($data);
            Log::error($e->getMessage());
        }
    }

    /**
     * 核销；使用会员卡 训练时长
     * @ApiMethod (POST)
     * @param int $type 核销类型：type 1=会员卡，2奖励卡
     * @param int $order_id 订单主键：order_id
     * @param int $reward_id 奖励主键：reward_id
     * @param int $gymnasium_id 场馆主键：gymnasium_id
     */
    public function verification()
    {
        if ($this->request->isPost()) {
            $type         = input('type');
            $order_id     = input('order_id');
            $reward_id    = input('reward_id');
            $gymnasium_id = input('gymnasium_id');
            $user_id      = 0;

            !$type && $this->error('请传入核销类型');
            !$gymnasium_id && $this->error('请传入场馆主键');
            if ($type == 1) {
                !$order_id && $this->error('请传入订单主键');
            }
            if ($type == 2) {
                !$reward_id && $this->error('请传入奖励主键');
            }

            // 验证场馆
            $gymnasium = Db::name('gymnasium')->where(['id' => $gymnasium_id])->field('is_join,is_activity,percentage,status')->find();
            if ($gymnasium) {
                $gymnasium['status'] != 1 && $this->error('场馆被禁用');
                if ($gymnasium['is_join'] != 1 && $type == 2) {
                    $this->error('您的场馆暂未参与新人奖励活动');
                }
            } else {
                $this->error('无效的场馆信息');
            }

            // 连接缓存
            $redis = new \Redis();
            $redis->pconnect(config('redis.host'), config('redis.port'), config('redis.timeout'));

            // 核销类型判断
            if ($type == 1) {
                // 验证订单
                $order = Db::name('order')->where(['id' => $order_id])->field('is_discount,gymnasium_id,end_number,numbers,good_name,end_time,status,good_type,user_id,total_price')->find();
                if ($order) {
                    // 验证会员卡是否属于该场馆
                    if ($order['gymnasium_id'] != $gymnasium_id) $this->error('会员卡不属于该场馆');
                    if ($order['status'] == 3) {
                        if ($order['good_type'] == 1 || $order['good_type'] == 2) {
                            $this->error('该会员卡次数已用完');
                        } else {
                            $this->error('该会员卡已到期');
                        }
                    }
                } else {
                    $this->error('无效的订单信息');
                }

                // 会员卡核销
                Db::startTrans();
                try {
                    // 分润只分一次
                    $find_income = Db::name('gymnasium_finance_income')->where(['gymnasium_id' => $gymnasium_id, 'order_id' => $order_id])->field('id')->find();
                    if (!$find_income) {
                        $money   = $order['total_price'] * (1 - $gymnasium['percentage']);
                        $user    = Db::name('user')->field('mobile,name')->find($order['user_id']);
                        $user_id = $order['user_id'];

                        // 拉新得卡不分润
                        if ($order['is_discount'] != 1) {
                            Db::name('gymnasium_finance')->where(['gymnasium_id' => $gymnasium_id])->setInc('balance', $money);
                            Db::name('gymnasium_finance_income')->insert([
                                'gymnasium_id' => $gymnasium_id,
                                'order_id'     => $order_id,
                                'money'        => $money,
                                'remarks'      => $user['name'] . '【' . $user['mobile'] . '】 主动核销 ' . '【' . self::$type[$order['good_type']] . '】' . $order['good_name'],
                                'createtime'   => time(),
                            ]);
                        }


                        // 删除db2 db3
                        $redis->select(2);
                        $redis->del($order['numbers']);
                        $redis->select(3);
                        $redis->del($order['numbers']);

                        // 计算【可用时间】
                        if ($order['good_type'] == 1) $end_time = time() + 3600 * 24 * 7 * $order['end_number'];
                        if ($order['good_type'] == 2) $end_time = time() + 3600 * 24 * 7 * $order['end_number'];
                        if ($order['good_type'] == 3) $end_time = time() + 3600 * 24 * 7;
                        if ($order['good_type'] == 4) $end_time = time() + 3600 * 24 * 30;
                        if ($order['good_type'] == 5) $end_time = time() + 3600 * 24 * 30;

                        // 卡种判断
                        if ($order['good_type'] == 1 || $order['good_type'] == 2) {
                            $update = [
                                'status'     => 2,
                                'use_time'   => time(),
                                'end_number' => $order['end_number'] - 1,
                                'end_time'   => $end_time,
                                'updatetime' => time(),
                            ];
                            if ($order['end_number'] - 1 == 0) $update['status'] = 3;
                        } else {
                            $update = [
                                'status'     => 2,
                                'use_time'   => time(),
                                'end_time'   => $end_time,
                                'updatetime' => time(),
                            ];
                        }

                        // 更新订单
                        Db::name('order')->where(['id' => $order_id])->update($update);

                        if ($update['status'] == 3) {
                            // 删除db4
                            $redis->select(4);
                            $redis->del($order['numbers']);
                        } else {
                            // 缓存【可用时间】
                            $redis->select(4);
                            $redis->setex($order['numbers'], $end_time - time(), '');
                        }

                    } else {
                        // 卡种判断
                        if ($order['good_type'] == 1 || $order['good_type'] == 2) {
                            $update = ['end_number' => $order['end_number'] - 1, 'updatetime' => time()];
                            if ($order['end_number'] - 1 == 0) $update['status'] = 3;

                            // 更新订单
                            Db::name('order')->where(['id' => $order_id])->update($update);
                        }
                    }

                    Db::commit();
                } catch (\Exception $e) {
                    Db::rollback();
                    $this->error($e->getMessage());
                }
            } else {
                // 验证优惠卡
                $extension = Db::name('extension')->where(['id' => $reward_id])->field('gymnasium_id,id,end_time,status,user_id')->find();
                if ($extension) {
                    $user_id = $extension['user_id'];
                    if ($extension['gymnasium_id'] != '' && $extension['gymnasium_id'] != $gymnasium_id) {
                        $this->error('核销失败,[该卡已经绑定其它场馆]');
                    }
                    if ($extension['status'] == 3) {
                        $this->error('核销失败,[该卡已到期]');
                    }
                } else {
                    $this->error('核销失败,[没有找到该卡信息]');
                }

                // 奖励卡核销
                Db::startTrans();
                try {
                    if ($extension['status'] == 0) {
                        $update = [
                            'status'       => 1,
                            'use_time'     => time(),
                            'end_time'     => time() + 3600 * 24 * 3,
                            'updatetime'   => time(),
                            'gymnasium_id' => $gymnasium_id
                        ];

                        // 更新优惠卡
                        Db::name('extension')->where(['id' => $reward_id])->update($update);

                        // 缓存【可用时间】删除db6
                        $redis->select(6);
                        $redis->del($extension['id']);
                        $redis->select(7);
                        $redis->setex($extension['id'], 3600 * 24 * 3, '');
                    }
                    Db::commit();
                } catch (\Exception $e) {
                    Db::rollback();
                    $this->error($e->getMessage());
                }
            }

            // 自动核销新用户
            $find = Db::name('user_gymnasium')->where(['user_id' => $user_id, 'gymnasium_id' => $gymnasium_id])->find();
            if (!$find) {
                Db::name('user_gymnasium')->insert(['user_id' => $user_id, 'gymnasium_id' => $gymnasium_id]);
            }

            // 训练信息
            $redis->select(5);
            $redis_train = $redis->get($user_id);
            if ($redis_train) {
                $train = unserialize($redis_train);
                // 防止今天多次核销
                if ($train['today'] != date('Y-m-d')) {
                    // 判断是不是昨天
                    if ($train['today'] == date("Y-m-d", strtotime("-1 day"))) {
                        $train['month_continuity_day']++;
                    } else {
                        $train['month_continuity_day'] = 1;
                    }
                    // 累计天数
                    if ($train['month'] == date('Y-m')) {
                        $train['cumulative_day']++;
                    } else {
                        $train['cumulative_day'] = 1;
                    }
                    $train['today'] = date("Y-m-d");
                    $train['month'] = date('Y-m');
                    $redis->set($user_id, serialize($train));
                }
            } else {
                $redis_train = [
                    // 当月连续天数
                    'month_continuity_day' => 1,
                    // 累计天数
                    'cumulative_day'       => 1,
                    // 今天
                    'today'                => date('Y-m-d'),
                    //当前月份
                    'month'                => date('Y-m'),
                ];
                $redis->set($user_id, serialize($redis_train));
            }

            $this->success('核销成功');
        } else {
            $this->error(ErrorCode::$ERROR['ERROR_METHOD']);
        }
    }

    /**
     * 退款 无需审核；校验是否使用、是否在有效期到期前48小时内
     * @ApiMethod (POST)
     * @param int $id 订单主键：id
     */
    public function refund()
    {
        if ($this->request->isPost()) {
            $id = input('id');
            !$id && $this->error('请传入订单主键');

            $order = Db::name('order')->field('good_name,good_id,status,numbers,total_price,user_id,validity_time')->find($id);
            if ($order) {
                // 验证订单
                if ($order['status'] == -1) $this->error('订单已取消');
                if ($order['status'] == 2) $this->error('订单包含的会员卡已使用');
                if ($order['status'] == 3) $this->error('订单包含的会员卡已到期');
                if ($order['status'] == 4) $this->error('订单已退款');
                if ($order['user_id'] != $this->auth->id) $this->error('此订单不属于该用户');

                // 验证有效期
                if ($order['validity_time'] - 3600 * 48 < time()) $this->error('到期前48小时不允许退款');

                Db::startTrans();
                try {
                    $params = [
                        'out_trade_no'  => $order['numbers'],
                        'out_refund_no' => $order['numbers'],
                        'total_fee'     => $order['total_price'] * 100,
                        'refund_fee'    => $order['total_price'] * 100,
                        'refund_desc'   => $order['good_name'] . '-退款',
                        'notify_url'    => Request::instance()->root(true) . '/api/v1/order/notify_refund/numbers/' . $order['numbers'],
                    ];
                    Service::createPay('wechat')->driver('wechat')->gateway('miniapp')->refund($params);
                    Db::commit();
                } catch (\Exception $e) {
                    Db::rollback();
                    $this->error($e->getMessage());
                }
            } else {
                $this->error('订单信息未找到');
            }

            $this->success('退款成功,到账稍有延迟');
        } else {
            $this->error(ErrorCode::$ERROR['ERROR_METHOD']);
        }
    }

    /**
     * 退款回调通知,退款成功在缓存中移除
     */
    public function notify_refund()
    {
        $numbers = $this->request->param('numbers');
        $data    = file_get_contents("php://input");

        Db::startTrans();
        try {
            // 更新订单
            Db::name('order')->where(['numbers' => $numbers])->update([
                'status'      => 4,
                'refund_time' => time(),
                'updatetime'  => time(),
            ]);

            // 返还用户优惠券,返还场馆优惠券
            $order = Db::name('order')->where(['numbers' => $numbers])->find();
            if ($order['is_discount'] == 1) {
                Db::name('good')->where(['id' => $order['good_id']])->setInc('stock');
                $good                = Db::name('good')->where(['id' => $order['good_id']])->field('type')->find();
                $find_extension_type = $good['type'] == 3 ? 1 : 2;
                Db::name('extension_001')->where(['user_id' => $order['user_id'], 'type' => $find_extension_type])->update([
                    'status'     => 0,
                    'use_time'   => 0,
                    'updatetime' => time(),
                ]);
            }

            // 删除db2 db3
            $redis = new \Redis();
            $redis->pconnect(config('redis.host'), config('redis.port'), config('redis.timeout'));
            $redis->select(2);
            $redis->del($numbers);
            $redis->select(3);
            $redis->del($numbers);

            Log::info('订单退款成功' . $numbers);
            Log::info($data);

            Db::commit();

            echo '<xml>
  <return_code><![CDATA[SUCCESS]]></return_code>
  <return_msg><![CDATA[OK]]></return_msg>
</xml>';
        } catch (\Exception $e) {
            Db::rollback();

            // 发送邮件警报
            (new Email)->to(config('alarm.email'))
                ->subject('订单退款成功,回调失败')
                ->message('<h1>错误信息：</h1>' . $e->getMessage() . '<h1>错误行号：</h1>' . $e->getLine() . '<h1>回调数据</h1><pre>' . json_encode($data, JSON_UNESCAPED_UNICODE) . '</pre>')
                ->send();

            // 记录错误日志
            Log::error('订单退款成功,回调失败');
            Log::error($data);
            Log::error($e->getMessage());
        }
    }

    public function test()
    {
        // 连接缓存
        $redis = new \Redis();
        $redis->pconnect(config('redis.host'), config('redis.port'), config('redis.timeout'));


        // 微信通知还是短信通知
//        $pay        = get_addon_config('epay');
//        $app_id     = $pay['wechat']['app_id'];
//        $app_secret = $pay['wechat']['app_secret'];
//        $data       = [
//            'date3'  => ['value' => date("Y-m-d H:i:s", time())],
//            'thing4' => ['value' => '尊敬的约汗么用户，您在【阿里巴巴】购买的【www】在72小时内到期，该会员卡在到期前48小时不可退款。请及时使用会员卡，祝您生活愉快！'],
//        ];
//        try {
//            $result = (new WxSdk($app_id, $app_secret))->subscribeSend('o7p1X4-l_5i3ZCuMRKJxxznHUyIc', 'kvmaVk0OuBOwrZKjTiMJ1je4JK6OeBzrtShS9lqakjU', 'pages/personal/system/index', $data);
//            var_dump($result);
//        } catch (\Exception $e) {
//        }
    }
}
